#include "MainHeader.h"
//Get the Major Arrays
//Currently only one exists

/*int LoadRoom(){
int Room = */

int LoadHeader(long Offset){
	long blah=0;
	int BGi=0;
	RHeader* RoomHeader=GameEngine->Members.RoomHeader;
	//CALLTOENGINETOLOADHEADER
	GameEngine->LoadHeader(Offset);
	CheckBoxes[Foreground].State(RoomHeader->bBg0==0x10);
	chkMC[0].State(RoomHeader->bBg0==0x10);
	CheckBoxes[Level].State(RoomHeader->bBg1==16);
	chkMC[1].State(RoomHeader->bBg1==16);
	CheckBoxes[Background].State(RoomHeader->bBg2==0x10);
    chkMC[2].State(RoomHeader->bBg2==0x10);
	EnableWindow(GetDlgItem(SceneWnd,cmdSEditForeground),(RoomHeader->bBg0==0x40 ? 1: 0));
	EnableWindow(GetDlgItem(SceneWnd,cmdSEditBack)      ,(RoomHeader->bBg2==0x40 ? 1: 0));
   	EnableWindow(GetDlgItem(SceneWnd,cmdSEditBG)        ,(RoomHeader->lBg3==0x40 ? 1: 0));
	CheckBoxes[ViewF].State(((RoomHeader->bBg0==0x10) || (RoomHeader->bBg0==0x40)));
	CheckBoxes[ViewL].State(RoomHeader->bBg1==16);
	CheckBoxes[ViewB].State(((RoomHeader->bBg2==0x10) || (RoomHeader->bBg2==0x40)));
	//CheckBoxes[viewBG].State((RoomHeader->lBg3==0x40) || (RoomHeader->lBg3==0xF0));
	CheckBoxes[ViewF].value(((RoomHeader->bBg0==0x10) || (RoomHeader->bBg0==0x40)));
	CheckBoxes[ViewL].value((RoomHeader->bBg1==16));
	CheckBoxes[ViewB].value(((RoomHeader->bBg2==0x10) || (RoomHeader->bBg2==0x40)));
    //CheckBoxes[viewBG].value((RoomHeader->lBg3==0x40) || (RoomHeader->lBg3==0xF0));
	//Check for BGi hack installed

	if((RoomHeader->bBg0==0x40) || (RoomHeader->bBg2==0x40) || (RoomHeader->lBg3==0x40||RoomHeader->lBg3==0xF0) || BGiInstall){
		EnableWindow(GetDlgItem(Main,cmdES),1);
    }else{
		EnableWindow(GetDlgItem(Main, cmdES),0);
	}
//	SetSceneControls();
	return 0;
}

int DrawLevel(){
	RECT rcMap;
	int i=0;
//	img[iRoom].Clear();
	ThisForeground->BImage.Create(ThisForeground->X*16,ThisForeground->Y*16);
    ThisForeground->BImage.SetPalette(GameEngine->Members.PcPalMem);
	ThisLevelData->BImage.Create(ThisLevelData->X*16,ThisLevelData->Y*16);
    ThisLevelData->BImage.SetPalette(GameEngine->Members.PcPalMem);
	ThisBackLayer->BImage.Create(ThisBackLayer->X*16,ThisBackLayer->Y*16);
    ThisBackLayer->BImage.SetPalette(GameEngine->Members.PcPalMem);
	ThisClipData->BImage.Create(ThisClipData->X*16,ThisClipData->Y*16);
   DrawAll=1;
	//for(i=0;i<2;i++){
	//   CheckBoxes[ViewF].value(i);
	//	CheckBoxes[ViewL].value(i);
	//	CheckBoxes[ViewB].value(i);
		DrawRoom();
	//}
	CurMapWidth = ThisLevelData->X;
	CurMapHeight =  ThisLevelData->Y;
	GetWindowRect(hwndMap,&rcMap);    
	nMaxHScroll[sHMap] = (ThisLevelData->X - (rcMap.right-rcMap.left)/16);//ThisLevelData->X/16;	// maximum H scroll
	nMaxVScroll[sVMap] = (ThisLevelData->Y - (rcMap.bottom-rcMap.top)/16 );		// maximu
	ChangeScrollbars(Main,1,sVMap);
	ChangeScrollbars(Main,0,sHMap);
	/*   frmMain.hsbMap.max = (ThisRoom.X) - 25
	frmMain.vsbMap.max = (ThisRoom.Y) - 17
	#define sHMap 1
#define sVMap 2*/
	InvalidateRect(hwndMap,0,1);
	//	rcMap.right = rcMap.right - rcMap.left;
	//	rcMap.bottom = rcMap.bottom - rcMap.top;
	//	CurMapWidth = (ThisLevelData->X<16 ? ThisLevelData->X*16:512);
	//	CurMapHeight = (ThisLevelData->Y<16 ? ThisLevelData->Y*16:512);
		  //   MoveWindow(hwndMap,0,0,CurMapWidth ,CurMapHeight,1);
	
	
	return 0;
}
int GetLayerData(Engine* mEngine, u8 compression, u8 Layer, u32 offset){
nRoomBuff* ELayer[5]={	ThisForeground,ThisLevelData,ThisBackLayer,ThisBackground,ThisClipData};//Edit Layer
mEngine->OpenFile();
GBA.ROM=mEngine->oFP();

fseek(GBA.ROM,offset,SEEK_SET);	
	if( compression == 0x10){
		fread(&ELayer[Layer]->X,sizeof(u8),1,GBA.ROM);		//ThisLevelData->X++;		// DISCH -- added inc
		fread(&ELayer[Layer]->Y,sizeof(u8),1,GBA.ROM);		//ThisLevelData->Y++;		// DISCH -- added inc
		// sprintf(buffer,"X is %x Y is %x",ThisLevelData->X,ThisLevelData->Y);
		// sMessage(buffer);
		fread(GBA.CompBuffer,sizeof(u8),64691,GBA.ROM);
		
		//GBA.ZMUncompRle(GBA.CompBuffer, (u8*)ThisLevelData->TileBuf2D ,ThisLevelData->X*ThisLevelData->Y, 1);
		ELayer[Layer]->BImage.Create(ELayer[Layer]->X*16,ELayer[Layer]->Y*16);
		ELayer[Layer]->BImage.SetPalette(GameEngine->Members.PcPalMem);
		memset(&ELayer[Layer]->TileBuf2D[0],0,0x20000);
		ELayer[Layer]->oSize=GBA.ZMUncompRle(ELayer[Layer]->X*ELayer[Layer]->Y, GBA.CompBuffer, (u8*)&ELayer[Layer]->TileBuf2D);
	}else if( compression==0x40){
        fseek(GBA.ROM,offset,SEEK_SET);	
		ELayer[Layer]->size=fgetc(GBA.ROM);
		
			if((ELayer[Layer]->size == 1)||(ELayer[Layer]->size >= 3)) {
				ELayer[Layer]->X = 64;
				ELayer[Layer]->Y = 32;
			}else if(ThisBackground->size == 2){
				ELayer[Layer]->X = 32;
				ELayer[Layer]->Y = 64;
			}else{
				
				ELayer[Layer]->X = 32; 
				ELayer[Layer]->Y = 32;
			}


		fseek(GBA.ROM,offset+4,SEEK_SET);
		fread(&GBA.CompBuffer,sizeof(u8),32691,GBA.ROM);
		//ELayer[Layer]->TileBuf2D.resize(0x20000);
		memset(&ELayer[Layer]->TileBuf2D, 0, 0x20000);
		//ThisBackLayer->oSize=GBA.LZ77UnComp(GBA.CompBuffer, decompbuf);
		u8*tmp=(u8*)ELayer[Layer]->TileBuf2D;
		ELayer[Layer]->oSize=GBA.LZ77UnComp(GBA.CompBuffer, tmp);
		ELayer[Layer]->BImage.Create(1024,1024);
		ELayer[Layer]->BImage.SetPalette(GameEngine->Members.PcPalMem);
		//memcpy(ELayer[Layer]->TileBuf2D,decompbuf,ELayer[Layer]->oSize);
	}
return 0;
}

int SaveLevel(FILE* fp, u32 HeaderOffset ){
	RHeader* RoomHeader=GameEngine->Members.RoomHeader;

//	GBA.REDIT = fopen(FilePath,"r+b");
	if(fp){
     //   while(1){ 
		GBA.ZMCompress(fp);
      //   if(RoomHeader->lBackLayer!=RoomHeader->lLevelData) break;
	//	}
	    SaveSprites();
		fseek(fp, HeaderOffset, SEEK_SET);
		
		
	
		fwrite(&RoomHeader->bTileset,sizeof(u8),1,fp);
		fwrite(&RoomHeader->bBg0,sizeof(u8),1,fp);
		fwrite(&RoomHeader->bBg1,sizeof(u8),1,fp);
		fwrite(&RoomHeader->bBg2,sizeof(u8),1,fp);
		fwrite(&RoomHeader->lBg3,sizeof(u32),1,fp);
		fwrite(&RoomHeader->lForeground,sizeof(u32),1,fp); 
		fwrite(&RoomHeader->lLevelData,sizeof(u32),1,fp);
		fwrite(&RoomHeader->lBackLayer,sizeof(u32),1,fp);
		fwrite(&RoomHeader->lClipData,sizeof(u32),1,fp); 
		fwrite(&RoomHeader->lBackgroundTSA,sizeof(u32),1,fp);
		fwrite(&RoomHeader->bUnknown1,sizeof(u8),1,fp);
		fwrite(&RoomHeader->TransForeground,sizeof(u8),1,fp);
		fwrite(&RoomHeader->iSep1,sizeof(u16),1,fp);
		fwrite(&RoomHeader->lSpritePointer,sizeof(u32),1,fp); 
		fwrite(&RoomHeader->bSpriteIndex1,sizeof(u8),1,fp);
		fwrite(&RoomHeader->bEventSwitch,sizeof(u8),1,fp);
		fwrite(&RoomHeader->iSep2,sizeof(u16),1,fp);
		fwrite(&RoomHeader->lSpritePointer2,sizeof(u32),1,fp); 
		fwrite(&RoomHeader->bSpriteIndex2,sizeof(u8),1,fp);
		fwrite(&RoomHeader->bEventSwitch2,sizeof(u8),1,fp);
		fwrite(&RoomHeader->iSeperator,sizeof(u16),1,fp);
		fwrite(&RoomHeader->lSpritePointer3,sizeof(u32),1,fp); 
		fwrite(&RoomHeader->bSpriteIndex3,sizeof(u8),1,fp);
		fwrite(&RoomHeader->bMiniMapRoomX,sizeof(u8),1,fp);
		fwrite(&RoomHeader->bMiniMapRoomY,sizeof(u8),1,fp);
		fwrite(&RoomHeader->bEffect,sizeof(u8),1,fp);
		fwrite(&RoomHeader->bSceneryYPos,sizeof(u8),1,fp);
		fwrite(&RoomHeader->bNothing,sizeof(u8),1,fp);
		fwrite(&RoomHeader->bMusic,sizeof(u8),1,fp);
		fwrite(&RoomHeader->blank,sizeof(u8),1,fp);
		
		SaveScroll();
     	SaveDoors();
	    LoadHeader(HeaderOffset);
	    
		
	}
	//fp = NULL;
	return 0;
}




int LoadMFROM(){
	//GetMFArrays();
		
	return 0;
}

int LoadData(){
RHeader* RoomHeader=GameEngine->Members.RoomHeader;
    if(RoomHeader->bBg0)GetLayerData(GameEngine,RoomHeader->bBg0, 0, RoomHeader->lForeground-0x8000000);
	if(RoomHeader->bBg1)GetLayerData(GameEngine,RoomHeader->bBg1, 1, RoomHeader->lLevelData-0x8000000);
	if(RoomHeader->bBg2)GetLayerData(GameEngine,RoomHeader->bBg2, 2, RoomHeader->lBackLayer-0x8000000);
	
	if(RoomHeader->lBg3==0x40){
		
		GetLayerData(GameEngine,RoomHeader->lBg3, 3, RoomHeader->lBackgroundTSA-0x8000000);
	}else if((RoomHeader->lBg3&0xF0)==0xF0){
        GetCBG();
		}
	GetLayerData(GameEngine,0x10, 4, RoomHeader->lClipData-0x8000000);
	return 0;
}


int GetCBG(){
	RHeader* RoomHeader=GameEngine->Members.RoomHeader;
    u32 palpos=0;
	u8 buffer[32192]={0};
	u32 size=0;
	int i =0;
	long pal[256]={0};
	u32 points[3]={0};
	int decmpsize=0;
    fseek(GBA.ROM,RoomHeader->lBackgroundTSA-0x8000000,SEEK_SET);
	fread(&ThisBackground->size,1,1,GBA.ROM);
	if(ThisBackground->size ==0){
		ThisBackground->X = 32; 
		ThisBackground->Y = 32;
	}else if((ThisBackground->size == 1)||(ThisBackground->size >= 3)) {
		ThisBackground->X = 64;
		ThisBackground->Y = 32;
	}else if(ThisBackground->size == 2){
		ThisBackground->X = 32;
		ThisBackground->Y = 64;
	}
    fread(&palpos,1, 1,GBA.ROM);
	fseek(GBA.ROM,RoomHeader->lBackgroundTSA-0x8000000+4,SEEK_SET);
	fread(points,1,12,GBA.ROM);
    
    fseek(GBA.ROM, points[0]-0x8000000,SEEK_SET);
	fread(buffer,1,32192,GBA.ROM);
	size=GBA.LZ77UnComp(buffer,(u8*)(GBA.GBAPal));

  
 
	GBA.DecodePal(GBA.GBAPal,pal,((size/2)+15) / 16, 0);//for test size is 1
	for(i=0;i<size/2;i++){
		GameEngine->Members.PcPalMem[palpos*16 + i]=pal[i];
	}

	memset(&GBA.CompBuffer,0,64691);

	fseek(GBA.ROM,points[1]-0x8000000,SEEK_SET);
	fread(GBA.CompBuffer,1,64691,GBA.ROM);


	decmpsize = GBA.LZ77UnComp(GBA.CompBuffer,buffer);
	ThisBackground->oSize = decmpsize;

	//ThisBackground->TileBuf2D.resize(0x20000);
	memset(&ThisBackground->TileBuf2D,0,0x20000);
	memcpy(&ThisBackground->TileBuf2D,buffer,ThisBackground->oSize);
	
    fseek(GBA.ROM,points[2]-0x8000000,SEEK_SET);
	//Seek the compressed Tileset
	fread(&GBA.CompBuffer,sizeof(char),32691,GBA.ROM);//Read compression
    size = GBA.LZ77UnComp(GBA.CompBuffer, buffer);
	memcpy(&GameEngine->Members.BGBuf[0x7DE0-size],buffer,size);


   BGImage.Load(GameEngine->Members.BGBuf,1024);
   //BGImage.
	return 0;
}
int DrawBackGround(Image* img){
	//We gotta do something about repeating
	RHeader* RoomHeader=GameEngine->Members.RoomHeader;
	
	int mX=ThisBackground->X;
	int mY=ThisBackground->Y;
	int difference = (mY>mX? mX:mY);
	int HorScenRep = 0;
	int VerScenRep = 0;
	nHScroll[SceneHScroll]=nVScroll[SceneVScroll]=nVScroll[STVScroll]=0;
	nMaxHScroll[SceneHScroll]=0;
	nMaxVScroll[SceneVScroll]=mY/8;
	nMaxVScroll[STVScroll]=2;//for now
	img->Create(ThisLevelData->X*16,ThisLevelData->Y*16);
	img->SetPalette(GameEngine->Members.PcPalMem);
	int i , x, y, scrX, scrY;
	i=x=y=scrX=scrY=0;//
	int rex = (mX == 64 ? 2 :  1);
	int rey = (mY == 64 ? 2 :  1);
	
	
	if(mX && mY){
				for(scrY = 0; scrY < rey; scrY++)
				{	
					for(scrX = 0; scrX < rex; scrX++)
					{
						for(y = 0; y < 32; ++y)
						{
							for(x = 0; x < 32; ++x)
							{
                                for(int WRep = 0; WRep<= ThisLevelData->X/mX + 1 ;WRep++){
									for(int HRep = 0;HRep<=ThisLevelData->Y/mY + 1;HRep++){
										img->Draw(BGImage,x*8 + scrX*256 + (WRep*(mX*8)) ,y*8+ scrY*256+ (HRep*(mY*8)) ,  ThisBackground->TileBuf2D[i]);
									}
								}
								i++;
							}
						}
					}
				}
	}

				return 0; 
}






int DrawRoom(){
RHeader* RoomHeader=GameEngine->Members.RoomHeader;
	u8 cSize=0;
	u8 fd=0;
	u32 fWidth=0,fHeight=0;
	//int Width=img[1].Width,Height=img[1].Height;
	int k =0;

	u16 Width=ThisLevelData->X<<4, Height=ThisLevelData->Y<<4;
	if(!((GameEngine->isZM())||(GameEngine->isMF()))) return 0;
	if(DrawAll==1){


    ThisForeground->Dirty =1 ;
	ThisLevelData->Dirty =1;
	ThisBackLayer->Dirty = 1;
	DrawAll=0;
	}

	img[iRoom].Create(Width,Width);
	
	ThisBackBuffer.Create(Width, Height);
	SetBkMode(ThisBackBuffer.DC(), TRANSPARENT);
	SetTextColor(ThisBackBuffer.DC(),RGB(255,255,255));
	img[iRoom].SetPalette(GameEngine->Members.PcPalMem);
	
 	
	TileImage.Load(GameEngine->Members.fGbuf,1024);
    
	
	  if(RoomHeader->lBg3& 0xF0 )	DrawBackGround(&ThisBackground->BImage); 
	
     ThisBackground->BImage.Blit(ThisBackBuffer.DC(),0,0,Width ,Width,0,0);
 
	if(CheckBoxes[ViewB].value()==BST_CHECKED){
		if(ThisBackLayer->Dirty){
		    ThisBackLayer->BImage.Create(ThisBackLayer->X*16,ThisBackLayer->Y*16);
            ThisBackLayer->BImage.SetPalette(GameEngine->Members.PcPalMem);
			DrawLayer(ThisBackLayer, RoomHeader->bBg2);//Backlayer
		    ThisBackLayer->Dirty=0;
	    } 
		if(RoomHeader->lBg3&0xF0){
			ThisBackLayer->BImage.TransBlit(ThisBackBuffer.DC(),0,0,Width, Height,0,0);
		}else{
            ThisBackLayer->BImage.Blit(ThisBackBuffer.DC(),0,0,Width, Height,0,0);
		}
	
	}
	
	if(CheckBoxes[ViewL].value()){
		if(ThisLevelData->Dirty){
		    ThisLevelData->BImage.Create(ThisLevelData->X*16,ThisLevelData->Y*16);
            ThisLevelData->BImage.SetPalette(GameEngine->Members.PcPalMem);	
			DrawLayer(ThisLevelData, RoomHeader->bBg1);//Level
			ThisLevelData->Dirty=0;
			
		}
	ThisLevelData->BImage.TransBlit(ThisBackBuffer.DC(),0,0,Width, Height,0,0);
	}
	
				
				
	

	if(CheckBoxes[ViewF].value()){
		if(ThisForeground->Dirty){
		  ThisForeground->BImage.Create(ThisForeground->X*16,ThisForeground->Y*16);
          ThisForeground->BImage.SetPalette(GameEngine->Members.PcPalMem);
		  DrawLayer(ThisForeground, RoomHeader->bBg0);//Foreground
		  ThisForeground->Dirty=0;
	   	}

        if(chkDoTrans.value() == 1)
		 ThisForeground->BImage.AlphaBlit(ThisBackBuffer.DC(),0,0,Width, Height,0,0,255);
	    else
		 ThisForeground->BImage.TransBlit(ThisBackBuffer.DC(),0,0,Width, Height,0,0);
	    
	}
	
	  
	
	
	
	
	img[iRoom].TransBlit(ThisBackBuffer.DC(),0,0,Width, Height,0,0);
	ShowSprites((u8)Combos[cSpriteSet].GetListIndex());
	DisplayDoors();
	if(ViewClip.value()   ==1)DrawClipIdent();
	if(ScrollCheck.value()==1)DrawScrolls  (cboScroll.GetListIndex());
	
	InvalidateRect(hwndMap,0,1);
     
	//SendMessage(hwndMap,WM_SIZE,1,0);

	return 0;
}


int DrawLayer(nRoomBuff* Map, u8 ctype){//img is the image to blit to 
	RHeader* RoomHeader=GameEngine->Members.RoomHeader;
int thisX=0,thisY=0,mX=0,mY=0;
u16 TILE = 0;
int i =0;
int X=Map->X;
int Y=Map->Y;
int ThisY=0;
int ThisX=0;
u16* TileBuf2D=(u16*)Map->TileBuf2D;
Image* pic=&Map->BImage;


pic->SetPalette(GameEngine->Members.PcPalMem);
	if(ctype == 0x40){//LZ 
		//pic->Create(ThisLevelData->X*16,ThisLevelData->Y*16);
		//pic->SetPalette(PcPalMem);
			//this type uses the background set for tiles.
			
			for(int ScenRep = 0;ScenRep<ThisLevelData->X;ScenRep++){
				for(thisX=0;thisX<Map->X;thisX++){
					for(thisY=0;thisY<Map->Y;thisY++){
						pic->Draw(BGImage, (ScenRep*32)+(thisX)* 8,(RoomHeader->bSceneryYPos-1)*16 + (thisY) * 8, TileBuf2D[(thisX)+(thisY*X )]);
					}
				}
			}
		
	}else 
	if(ctype == 0x10){
	//	for(thisY=Map->DrawRect.top;thisY<(Map->DrawRect.bottom);thisY++){

	//		for(thisX = Map->DrawRect.left; thisX < (Map->DrawRect.right);thisX++){// from here if something is enabled then draw it 
		for(thisY=0;thisY<(Map->Y);thisY++){

			for(thisX=0;thisX<(Map->X);thisX++){// from here if something is enabled then draw it 
						TILE =(TileBuf2D[thisX+(thisY * X)]);
						BitBlt(pic->DC(),(thisX)<<4, (thisY)<<4,16,16,img[iTileset].DC(),(TILE%16)<<4,(TILE>>4)<<4,SRCCOPY);
					
	   
				}
			}
		
		//Rect to draw

	}
   


	return 0;
}


